package com.example.myinput;

import android.os.Build;
import android.os.IBinder;

import android.view.InputEvent;
import java.lang.reflect.Method;

public class InputManger {
    private Object manager;
    private Method injectMethod;
    public static Class<?> getInputManagerClass() {
        try {
            // Parts of the InputManager class have been moved to a new InputManagerGlobal class in Android 14 preview
            return Class.forName("android.hardware.input.InputManagerGlobal");
        } catch (ClassNotFoundException e) {
            return android.hardware.input.InputManager.class;
        }
    }
    public InputManger(){
        try {
            String release =Build.VERSION.RELEASE;
            System.out.println("Android :"+release);
            if(Build.VERSION.SDK_INT<29){
                System.out.println("Android<10");
                IBinder binder=getService("input");
                Class<?>subClass=Class.forName("android.hardware.input.IInputManager$Stub");
                Method asInterface=subClass.getMethod("asInterface",IBinder.class);
                manager=asInterface.invoke(null,binder);
            }else{
                System.out.println("Android>=10");
                Class<?> inputManagerClass =getInputManagerClass();
                Method getInstanceMethod = inputManagerClass.getDeclaredMethod("getInstance");
                manager=getInstanceMethod.invoke(null);
            }
            injectMethod=manager.getClass().getMethod("injectInputEvent",InputEvent.class,int.class);
            injectMethod.setAccessible(true);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    public static IBinder getService(String name){
        try {
            Class<?> smClass=Class.forName("android.os.ServiceManager");
            Method getService =smClass.getDeclaredMethod("getService",String.class);
            return (IBinder)getService.invoke(null,name);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    public boolean injectInputEvent(InputEvent event,int mode){
        try {
            return (boolean) injectMethod.invoke(manager, event, mode);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
    private static volatile InputManger instance;
    public static synchronized InputManger getInstance(){
        if (instance == null) {
            synchronized (InputManger.class) {
                if (instance == null) {
                    instance = new InputManger();
                }
            }
        }
        return instance;
    }

    static {
        System.load("/data/local/tmp/libnative-lib.so");
    }
    public native void injectBezier(int x1,int y1,int x2,int y2,int num,int mLeaveHeightLength,int mh,int durationMs,int willContinue,int pressure);
    public native void injectTrajectory(int x1,int y1,int x2,int y2,int num,int durationMs,int willContinue,int pressure);
    public native void injectStop(int x,int y,int num,int durationMs,int pressure,int isUp);
}
